package com.ruoyi.material.util;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.log4j.Log4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.channels.FileChannel;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @program: MSS
 * @description: 文件与文件夹的工具类
 * @author: cyw
 * @create: 2021-07-21 10:42
 **/

public class FileUtil {
    private static Logger log = LoggerFactory.getLogger(FileUtil.class);
    /**
     * 根据路径删除指定的目录或文件，无论存在与否
     * @param deletePath
     * @return
     */
    public static boolean deleteFolder(String deletePath) {
       File file = new File(deletePath);
       if (!file.exists()){
           return false;
       }
       if (file.isFile()){
           return deleteFile(deletePath);
       }else {
           return deleteDirectory(deletePath);
       }
    }

    /**
     *  删除单个文件
     * @param filePath
     * @return
     */
    public static boolean deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.isFile() && file.exists()){
            file.delete();
            return true;
        }
        return false;
    }

    /**
     * 删除目录（文件夹）以及目录下的文件
     * @param dirPath
     * @return
     */
    public static boolean deleteDirectory(String dirPath) {
        File dirFile = new File(dirPath);
        // 如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        boolean flag = true;
        // 获得传入路径下的所有文件
        File[] files = dirFile.listFiles();
        // 循环遍历删除文件夹下的所有文件(包括子目录)
        if (files != null){
            for (File file: files){
                if (file.isFile()){
                   flag =  deleteFile(file.getAbsolutePath());
                   if (!flag){
                       break;
                   }
                }else{
                    flag = deleteDirectory(file.getAbsolutePath());
                    if (!flag){
                        break;
                    }
                }
            }
        }
        return true;
    }

    /**
     * 创建单个文件
     *
     * @param filePath 文件所存放的路径
     * @return
     */
    public static boolean createFile(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {// 判断文件是否存在
            return false;
        }
        if (filePath.endsWith(File.separator)) {// 判断文件是否为目录
            return false;
        }
        if (!file.getParentFile().exists()) {// 判断目标文件所在的目录是否存在

            if (!file.getParentFile().mkdirs()) {// 判断创建目录是否成功
                return false;
            }
        }
        try {
            if (file.createNewFile()) {// 创建目标文件

                return true;
            } else {
                log.error("创建文件失败");
                return false;
            }
        } catch (IOException e) {// 捕获异常
            e.printStackTrace();
            log.error("创建文件失败 [{}]",e.getMessage());
            return false;
        }
    }

    /**
     * 创建目录(如果目录存在就删掉目录)
     *
     * @param destDirName 目标目录路径
     * @return
     */
    public static boolean createDir(String destDirName) {
        File dir = new File(destDirName);
        if (dir.exists()) {// 判断目录是否存在
            //return false;
            return deleteDirectory(destDirName);
        }
        if (!destDirName.endsWith(File.separator)) {// 结尾是否以"/"结束
            destDirName = destDirName + File.separator;
        }
        if (dir.mkdirs()) {// 创建目标目录
            return true;
        } else {
            return false;
        }
    }


    /**
     * 复制文件
     * @param from 源文件
     * @param to 复制文件
     * @throws IOException
     */
    public static void copyNio(String from, String to) {
        FileChannel input = null;
        FileChannel output = null;

        try {
            input = new FileInputStream(new File(from)).getChannel();
            output = new FileOutputStream(new File(to)).getChannel();
            output.transferFrom(input, 0, input.size());
        } catch (Exception e) {
            log.error( "copyNio", "error occur while copy", e);
        } finally {
            try {
                input.close();
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }



    /**
     * 获取文件的真实路径
     * @Param filePath 文件记录的路径
     */
    public static String getRealFilePath(String filePath){
        // 本地资源路径
        String localPath = RuoYiConfig.getProfile();
        // 数据库资源地址
        String realFileName = localPath + StringUtils.substringAfter(filePath, Constants.RESOURCE_PREFIX);
        return realFileName;
    }

    /**
     * 遍历所有文件，压缩
     *
     * @param resource       源文件目录
     * @param parentPath 压缩文件目录
     * @param zos        文件流
     */
    public static void writeZip(String  resource, String parentPath, ZipOutputStream zos) {
        File file = new File(resource);
        if (file.isDirectory()) {
            //目录
            parentPath += file.getName() + File.separator;
            File[] files = file.listFiles();
            for (File f : files) {
                writeZip(f.getAbsolutePath(), parentPath, zos);
            }
        } else {
            //文件
            try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
                //指定zip文件夹
                ZipEntry zipEntry = new ZipEntry(parentPath + file.getName());
                zos.putNextEntry(zipEntry);
                int len;
                byte[] buffer = new byte[1024 * 10];
                while ((len = bis.read(buffer, 0, buffer.length)) != -1) {
                    zos.write(buffer, 0, len);
                    zos.flush();
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e.getMessage(), e.getCause());
            }
        }
    }

    /**
     * 压缩文件
     *
     * @param sourceFilePath 源文件路径
     * @param zipFilePath    压缩后文件存储路径
     * @param zipFilename    压缩文件名
     */
    public static void compressToZip(String sourceFilePath, String zipFilePath, String zipFilename) {
        File sourceFile = new File(sourceFilePath);
        File zipPath = new File(zipFilePath);
        if (!zipPath.exists()) {
            zipPath.mkdirs();
        }
        File zipFile = new File(zipPath + File.separator + zipFilename);
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
            writeZip(sourceFile.getAbsolutePath(), "", zos);
            //文件压缩完成后，删除被压缩文件
            log.info("删除被压缩文件[" + sourceFile + "]标志：{}");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage(), e.getCause());
        }
    }

    /**
     * 在文件末尾添加文本
     * @param filePath 文件路径
     * @param newContent 添加内容
     * @throws IOException
     */
    public static  void addContent(String filePath, String newContent) throws IOException {
        RandomAccessFile randomAccessFile=new RandomAccessFile(filePath, "rw");
        long fileLength=randomAccessFile.length();
        randomAccessFile.seek(fileLength);
        randomAccessFile.write(newContent.getBytes("UTF-8"));
        randomAccessFile.close();
    }

}
